package cn.akwangl.spring.bean.definition;

import cn.akwangl.spring.bean.factory.DefaultUserFactory;
import cn.akwangl.spring.bean.factory.UserFactory;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.serviceloader.ServiceLoaderFactoryBean;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.Iterator;
import java.util.ServiceLoader;

/**
 * 特殊 Bean 实例化Demo
 * 方式一 : ServiceLoad
 * 1. JDK {@link ServiceLoader} 原生API 初始化Bean
 * 2. springframework 适配 {@link ServiceLoaderFactoryBean}
 * 方式二 : springframework API
 * 1. {@link AutowireCapableBeanFactory#createBean(Class)}
 * 2. {@link BeanDefinitionRegistry#registerBeanDefinition(String, BeanDefinition)}
 *
 * @author youyongkun
 * @date 2021/6/30 20:35
 */
public class SpecialBeanInstantiationDemo {
    public static void main(String[] args) {
        // JDK 原生ServiceLoad使用
        serviceLoadDemo();

        // springframework ServiceLoad 适配
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("META-INF/special-bean-instantiation-context.xml");
        ServiceLoader<UserFactory> userFactoryServiceLoader = applicationContext.getBean("userFactoryServiceLoader", ServiceLoader.class);

        displayServiceLoad(userFactoryServiceLoader);

        // AutowireCapableBeanFactory#createBean
        AutowireCapableBeanFactory autowireCapableBeanFactory = applicationContext.getBeanFactory();
        UserFactory userFactory = autowireCapableBeanFactory.createBean(DefaultUserFactory.class);
        System.out.println("AutowireCapableBeanFactory#createBean 创建UserFactory" + userFactory.createUser());
    }

    public static void serviceLoadDemo() {
        ServiceLoader<UserFactory> serviceLoader = ServiceLoader.load(UserFactory.class, Thread.currentThread().getContextClassLoader());
        displayServiceLoad(serviceLoader);
    }

    private static void displayServiceLoad(ServiceLoader<UserFactory> serviceLoader) {
        Iterator<UserFactory> iterator = serviceLoader.iterator();
        while (iterator.hasNext()) {
            UserFactory userFactory = iterator.next();
            System.out.println("JDK ServiceLoader 方式加载Bean: " + userFactory.createUser());
        }
    }
}
